package tools.gis.antennaReader;


import java.io.File;
import java.io.Serializable;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Vector;

import javax.swing.JOptionPane;

import org.geotools.data.DataStore;
import org.geotools.data.DataStoreFinder;
import org.geotools.data.FeatureSource;
import org.geotools.feature.FeatureCollection;
import org.geotools.feature.FeatureIterator;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;

import tools.Log;
import tools.settings.SettingsAdapter;
import datatypes.Antenna;
import datatypes.AntennaType;
import datatypes.FrequencyRange;
import datatypes.Technology;
import java.util.ArrayList;

/**
 * Leest een antennelijst in en sorteert deze in sites
 * 
 * @author Bart Moens
 *
 */
public class AntennaSiteReader {
	
	
	public List<AntennaSite> getAntennaSiteList(File file) throws Exception {
		
		List<Antenna> antennaList = new LinkedList<Antenna>();
		List<AntennaSite> siteList = new LinkedList<AntennaSite>();
		try {
			// Connection parameters
			Map<String,Serializable> connectParameters = new HashMap<String,Serializable>();

			connectParameters.put("url", file.toURI().toURL());
			connectParameters.put("create spatial index", true );
			DataStore dataStore = DataStoreFinder.getDataStore(connectParameters);

			// we are now connected
			String[] typeNames = dataStore.getTypeNames();
			String typeName = typeNames[0];

			Log.add(new AntennaSiteReader(),"Reading content " + typeName);

			FeatureSource<SimpleFeatureType, SimpleFeature> featureSource;
			FeatureCollection<SimpleFeatureType, SimpleFeature> collection;
			FeatureIterator<SimpleFeature> iterator;

			featureSource = dataStore.getFeatureSource(typeName);
			collection = featureSource.getFeatures();
			iterator = collection.features();

//			SimpleFeature sf = iterator.next();
			Antenna defaultAntenna = new Antenna(iterator.next());
			defaultAntenna.setOperator("");
			defaultAntenna.setHeight(30);
			defaultAntenna.setPower(30);
			defaultAntenna.setType(AntennaType.directional);
			defaultAntenna.setOperatorSite(false);
			defaultAntenna.setActive(false);
			
			try {
				while (iterator.hasNext() ) {
					SimpleFeature feature = iterator.next();
					Antenna af = new Antenna(feature);
					af.setActive(true);
					af.setType(AntennaType.directional);
					antennaList.add(af);
				}
			}
			finally {
				if( iterator != null ){
					iterator.close();
				}
			}



			Log.add(new AntennaSiteReader(),"Generating SiteList");
			for (Antenna a: antennaList) {
				//check if the site allready exists 
				//if so, add
				boolean newSite = true;
				for (AntennaSite as : siteList) {
					if (a.getX() == as.getX() && a.getY() == as.getY()) {
						as.addAntenna(a);
						newSite = false;
						break;
					}
				}
				
				//if not create new site and add
				if (newSite) {
					Antenna tmp = defaultAntenna.clone();
					tmp.setX(a.getX());
					tmp.setY(a.getY());
					AntennaSite as = new AntennaSite(a.getX(), a.getY(),tmp );
					as.addAntenna(a);
					siteList.add(as);
				}
			}

		} catch (Exception ex) {
			ex.printStackTrace();
			System.exit(1);
		}
		

		Log.add(new AntennaSiteReader(),"Sites found: " + siteList.size() + " with " + antennaList.size() + " antenna's");
		return siteList;
		
	}
        
        public List<AntennaSite> getAntennaSiteListNewNetwork(File file, Technology technology) throws Exception {

		List<Antenna> antennaList = new LinkedList<Antenna>();
		List<AntennaSite> siteList = new LinkedList<AntennaSite>();
		try {
			// Connection parameters
			Map<String,Serializable> connectParameters = new HashMap<String,Serializable>();

			connectParameters.put("url", file.toURI().toURL());
			connectParameters.put("create spatial index", true );
			DataStore dataStore = DataStoreFinder.getDataStore(connectParameters);

			// we are now connected
			String[] typeNames = dataStore.getTypeNames();
			String typeName = typeNames[0];

			Log.add(new AntennaSiteReader(),"Reading content " + typeName);

			FeatureSource<SimpleFeatureType, SimpleFeature> featureSource = dataStore.getFeatureSource(typeName);
			FeatureCollection<SimpleFeatureType, SimpleFeature> collection = featureSource.getFeatures();
			FeatureIterator<SimpleFeature> iterator = collection.features();


			ArrayList<SimpleFeature> tmplist = new ArrayList<SimpleFeature>();
			while(iterator.hasNext()){
				SimpleFeature feature = iterator.next();
				if(Double.parseDouble(feature.getAttribute("HEIGHT").toString()) >= 20){
					tmplist.add(feature);
				}
			}
			System.out.println(tmplist.size());
			for(int i = 0; i < tmplist.size(); i++){
				SimpleFeature feature = tmplist.get(i);
				//double x = ((Geometry)feature.getDefaultGeometry()).getCentroid().getX();
				//double y = ((Geometry)feature.getDefaultGeometry()).getCentroid().getY();
				Antenna antenna = new Antenna(feature, technology);
				antenna.setOperator("");
				antenna.setHeight(Double.parseDouble(feature.getAttribute("HEIGHT").toString()));
				antenna.setFrequency(technology.getFrequency());
				antenna.setPower(technology.getMaxInputPower(antenna.getCellType()));
				antenna.setGain(technology.getBSAntennaGain_default(antenna.getCellType()));
				antenna.setType(AntennaType.directional);
				antenna.setOperatorSite(false);
				antenna.setActive(false);
				//antenna.setX(x);
				//antenna.setY(y);
				antennaList.add(antenna);
			}

			Log.add(new AntennaSiteReader(),"Generating SiteList2");
			int index = 1;
			for (Antenna a: antennaList) {
				//check if the site already exists
				//if so, add
				boolean newSite = true;
				for (AntennaSite as : siteList) {
					if (a.getX() == as.getX() && a.getY() == as.getY()) {
						as.addAntenna(a);
						newSite = false;
						break;
					}
				}

				//if not create new site and add
				if (newSite) {
					Antenna tmp = a.clone();
					AntennaSite as = new AntennaSite(a.getX(), a.getY(), tmp);
					as.addAntenna(a);
					siteList.add(as);
					System.out.println("New site: "+index+" of "+tmplist.size());
					index++;
				}
			}


		} catch (Exception ex) {
			System.out.println(ex.getMessage().toString());
			ex.printStackTrace();
			System.exit(1);
		}


		Log.add(new AntennaSiteReader(),"Sites found: " + siteList.size() + " with " + antennaList.size() + " antenna's");

		return siteList;

	}
	
	
	public String selectedOperagor = "";
	
	public Antenna[] filterSiteListGUI(List<AntennaSite> sitelist) {
		Set<String> operators = new HashSet<String>();
		operators.add("Use only sites");
		for (AntennaSite as : sitelist) {
			for (Antenna a : as.getAntennas()) {
				operators.add(a.getOperator());
			}
		}
		//operators
		Object[] options = operators.toArray(new String[0]);
		
		//frequency
		Vector<FrequencyRange> fr = SettingsAdapter.getInstance().getFrequencyRange();
		
		String freqs = SettingsAdapter.getInstance().getTechnologyName() + ": " + fr.toString();	
		
		//selection dialog
		selectedOperagor = (String)JOptionPane.showInputDialog(
                null,
                "Select operator for basic antennaset\n\n"
                + "Directed antennas at same location\n"
                + "will be merged to omnidirectionals.\n\n"
                + "Extra filter for technology & frequency:\n"
                + freqs + "\n  ",
                "Select Operator",
                JOptionPane.PLAIN_MESSAGE,
                null,
                options,
                null);



		Log.add(new AntennaSiteReader(),"Filtering site-list");
		
		for (AntennaSite as : sitelist) {
			as.filterOnOperator(selectedOperagor);
			as.filterOnFrequency(fr);
			as.transformToOmniAntennas(fr);
		}
		int ac = 0;
		int acSit = 0;
		int de = 0;
		for (AntennaSite as : sitelist) {
			boolean added = false;
			for (Antenna an : as.getAntennas()) {
				if (an.getActive()) { 
					ac++;
					added = true;
				}
				else {
					de++;
				}
			}
			if (added)
				acSit++;
	
		}

		
		Log.add(new AntennaSiteReader(),"After filtering: " + sitelist.size() + " sites with " + ac + " active antenna's @ " + acSit + " Sites and " + de + " inactives @ " + de + " sites");
		
		Log.add(new AntennaSiteReader(),"Running KMeans on antennas");

		List<Antenna> list = new LinkedList<Antenna>();
		for (AntennaSite as : sitelist) {
			for (Antenna an : as.getAntennas()) {
				list.add(an);
			}
		}
		KMeans km = new KMeans(50, list);
		Antenna[] aa = km.runKMeans();
		Log.add(new AntennaSiteReader(),"KMeans done");
		return aa;
		
		
	}
}